/**
 * Copyright 2011 FeedDreamwork SIG
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package org.feeddreamwork.feed;

import java.io.*;

import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.*;
import javax.xml.transform.stream.*;

import org.feeddreamwork.*;
import org.w3c.dom.*;
import org.xml.sax.*;

public final class XMLUtils {
	private static DocumentBuilderFactory dbFactory = DocumentBuilderFactory
			.newInstance();
	private static TransformerFactory transFactory = TransformerFactory
			.newInstance();

	static {
		try {
			dbFactory
					.setFeature(
							"http://apache.org/xml/features/nonvalidating/load-external-dtd",
							false);
		} catch (ParserConfigurationException e) {
			throw new RuntimeException(e);
		}
	}

	public static Document newDocument() {
		try {
			DocumentBuilder db = dbFactory.newDocumentBuilder();
			return db.newDocument();
		} catch (ParserConfigurationException e) {
			throw new RuntimeException(e);
		}
	}

	public static Document parseDocument(String source) throws IOException,
			SAXException {
		StringReader reader = null;
		try {
			reader = new StringReader(source);
			skipBom(reader);
			DocumentBuilder db = dbFactory.newDocumentBuilder();
			return db.parse(new InputSource(reader));
		} catch (ParserConfigurationException e) {
			throw new RuntimeException(e);
		} finally {
			reader.close();
		}
	}

	public static void outputNode(Node source, Writer writer) {
		Utils.throwIfNull(source);
		Utils.throwIfNull(writer);

		try {
			Transformer trans = transFactory.newTransformer();
			trans.transform(new DOMSource(source), new StreamResult(writer));
		} catch (TransformerException e) {
			throw new RuntimeException(e);
		}
	}

	public static String findSimpleElement(Element node, String name) {
		Utils.throwIfNull(node);
		Utils.throwIfNullOrEmpty(name);

		NodeList childNodes = node.getChildNodes();
		for (int i = 0; i < childNodes.getLength(); i++) {
			Node childNode = childNodes.item(i);
			if (childNode.getNodeName().equals(name))
				return childNode.getTextContent();
		}
		return null;
	}

	public static Element appendSimpleElement(Element node, String name,
			String value) {
		Utils.throwIfNull(node);
		Utils.throwIfNullOrEmpty(name);

		Element result = node.getOwnerDocument().createElement(name);
		result.setTextContent(value);
		node.appendChild(result);
		return result;
	}

	private static void skipBom(StringReader reader) throws IOException {
		final int BOM_UTF16BE = 0xFEFF;
		Utils.throwIfNull(reader);

		int bom = reader.read();
		if (bom == BOM_UTF16BE)
			return;
		reader.reset();
	}

	private XMLUtils() {
	}
}
